package org.truenewx.tnxjee.repo.mybatis.model.query;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.truenewx.tnxjee.model.query.*;

import java.io.Serial;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * MybatisPlus的分页查询结果适配器
 *
 * @param <T> 实体类型
 */
public class QueryResultPage<T> extends QueryResult<T> implements IPage<T> {

    @Serial
    private static final long serialVersionUID = 7813258247832208061L;

    protected Querying querying;
    private Map<String, String> fieldColumnNameMapping;

    public QueryResultPage(Querying querying) {
        this.querying = querying;
        this.paged = Paged.of(querying, -1);
    }

    public QueryResultPage(Querying querying, QueryResult<T> qr) {
        this.querying = querying;
        this.records = qr.getRecords();
        this.paged = qr.getPaged();
    }

    public QueryResultPage(IPage<T> page) {
        if (page instanceof Querying) {
            this.querying = (Querying) page;
        }
        this.paged = new Paged((int) page.getSize(), (int) page.getCurrent(), page.getTotal());
        setRecords(page.getRecords());
    }

    public void setFieldColumnNameMapping(Map<String, String> fieldColumnNameMapping) {
        this.fieldColumnNameMapping = fieldColumnNameMapping;
    }

    @Override
    public List<OrderItem> orders() {
        List<FieldOrder> fieldOrders = this.querying.getOrders();
        if (fieldOrders != null) {
            return fieldOrders.stream().map(fieldOrder -> {
                String orderName = fieldOrder.getName();
                if (this.fieldColumnNameMapping != null) { // 字段名转换为表列名
                    String columnName = this.fieldColumnNameMapping.get(orderName);
                    if (columnName != null) {
                        orderName = columnName;
                    }
                }
                if (fieldOrder.isDesc()) {
                    return OrderItem.desc(orderName);
                } else {
                    return OrderItem.asc(orderName);
                }
            }).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public IPage<T> setRecords(List<T> records) {
        this.records = records;
        return this;
    }

    @Override
    @JsonIgnore
    public long getTotal() {
        return this.paged.getTotal();
    }

    @Override
    public IPage<T> setTotal(long total) {
        this.paged = Paged.of(this.querying, total);
        return this;
    }

    @Override
    @JsonIgnore
    public long getSize() {
        return this.querying.getPageSize();
    }

    @Override
    public IPage<T> setSize(long size) {
        this.querying.setPageSize((int) size);
        return this;
    }

    @Override
    @JsonIgnore
    public long getCurrent() {
        return this.querying.getPageNo();
    }

    @Override
    public IPage<T> setCurrent(long current) {
        this.querying.setPageNo((int) current);
        return this;
    }

    @Override
    @JsonIgnore
    public long getPages() {
        return IPage.super.getPages();
    }

    @Override
    public boolean searchCount() {
        return this.querying.getIgnoring() != QueryIgnoring.TOTAL;
    }

}
